#include "util.hpp"
#include <cstdio>
#include <vector>
#include <functional>

using func_t = std::function<void ()>;

// 下面的两个都是宏函数
#define INIT(v) do{\
    v.push_back(printLog);\
    v.push_back(download);\
    v.push_back(executeSql);\
}while(0);

#define EXEC_OTHER(cbs) do{\
    for(auto cb: cbs) cb();\
}while(0);

int main(void){
    std::vector<func_t> cbs;
    INIT(cbs);     // 初始化 cbs 数组
    // cbs.push_back(printLog);
    // cbs.push_back(download);
    // cbs.push_back(executeSql);

    setNonBlock(0);
    char buffer[1024];
    while(true){
        std::cout << ">>> ";
        fflush(stdout);   // 把上面的 >>> 刷新出来
        // Linux 里面，键盘的输入也是相当于是一种文件输入的哦。ctrl + d / ctrl + z 就是文件结束符

        ssize_t s = read(0, buffer, sizeof(buffer) - 1);
        if(s > 0){
            buffer[s - 1] = 0;   // buffer[s] = 0; 的话，会有一个换行的效果的哦
            std::cout << "echo# " << buffer << std::endl;
        }else if(s == 0){
            std::cout << "read end" << std::endl;
            break;
        }else{
            // std::cout << "......" << std::endl;
            // 1. 我不输入的时候是会执行这里的代码的，但是不算错误的，只不过以错误的形式返回了
            // 2. 如何区分是真的错了，还是底层没有输入数据呢？ --> 单词的返回值是解决不了的 --> 但是退出码被重定义了
            std::cout << "s : " << s << " errno: " << strerror(errno) << std::endl;
            // 所以有了下面的代码
            // std::cout << "EAGAIN: " << EAGAIN << " EWOULDBLOCK: " << EWOULDBLOCK << std::endl;
            if(errno == EAGAIN ){
                std::cout << "我没有错误,只是没有数据" << std::endl;
                EXEC_OTHER(cbs);   // 执行其它的函数(事件)
            }
            else if(errno == EINTR){   
                continue;
            }else{
                // 剩下的 errno 都是由错误的
                std::cout << "s: " << s << " errno: " << strerror(errno) << std::endl;
                break;
            }
        }

        // 非阻塞：在轮询的空闲时间内，执行其它的函数
        // EXEC_OTHER(cbs);    // 模拟函数调用
        // for(auto const &cb: cbs) cb();  

        sleep(1);
    }

    return 0;
}
